package com.linkstec.base.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.linkstec.base.constant.SysConstant;
import com.linkstec.base.service.WechatConfigService;
import com.linkstec.base.util.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class WechatConfigServiceImpl implements WechatConfigService {

    Logger logger = LoggerFactory.getLogger(WechatConfigServiceImpl.class);
    @Autowired
    PropUtil propUtil;
    @Autowired
    RedisUtil redisUtil;

    @Override
    public DataResultUtil getConfig(String url) {
        // 获取签名
        JSONObject signatureJSON = getSignature(url);
        // 封装结果
        JSONObject data = new JSONObject();
        data.put("appId", propUtil.wechat_app_id);
        data.put("timestamp", signatureJSON.getString("timestamp"));
        data.put("nonceStr", signatureJSON.getString("nonceStr"));
        data.put("signature", signatureJSON.getString("signature"));
        return DataResultUtil.getSuccessResult(data);
    }

    public JSONObject getSignature(String url){
        JSONObject signatureJSON = new JSONObject();
        // 1.随机字符串 其长度是指定的字符数。
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        signatureJSON.put("nonceStr", nonceStr);
        // 2.获取签名时间戳 单位为秒
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        signatureJSON.put("timestamp", timestamp);
        // 3.获取jsapi_ticket
        String ticket = getJsapiTicket();
        // 对ticket加密得到签名
        logger.info("加密签名：ticket = {}，nonceStr = {}，timestamp = {}，url = {}", ticket, nonceStr, timestamp, url);
        String unEncryptStr = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = SHA1Util.getSha1(unEncryptStr);
        signatureJSON.put("signature", signature);
        logger.info("加密签名结果：signature = {}", signature);
        return signatureJSON;
    }


    public String getJsapiTicket() {
        String ticket = (String) redisUtil.get(SysConstant.jsapi_ticket);
        if (!StringUtils.isEmpty(ticket)) {
            return ticket;
        }
        //获取token
        String token = getAccessToken("client_credential");
        //包装json
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("access_token", token);
        jsonObject.put("type", "jsapi");
        //获取JsapiTicket
        String json = HttpClientUtil.sendGet(propUtil.prop_wechat_api_url + propUtil.prop_wechat_ticket_url, jsonObject);
        if (!StringUtils.isEmpty(json)) {
            JSONObject data = JSONObject.parseObject(json);
            String newTicket = data.getString("ticket");
            if (StringUtils.isNotBlank(newTicket)) {
                redisUtil.set(SysConstant.jsapi_ticket, newTicket, SysConstant.base_redis_time);
                return newTicket;
            }
        }
        logger.error("JsapiTicket获取失败，jsonObject={}", jsonObject);
        throw new RuntimeException("JsapiTicket获取失败!");
    }

    @Override
    public String getAccessToken(String grant_type) {
        String token = (String) redisUtil.get(SysConstant.access_token);
        if (!StringUtils.isEmpty(token)) {
            return token;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("grant_type", grant_type);
        jsonObject.put("appid", propUtil.wechat_app_id);
        jsonObject.put("secret", propUtil.wechat_secret);
        //获取token
        String accessToken = HttpClientUtil.sendGet(propUtil.prop_wechat_api_url + propUtil.prop_wechat_token_url, jsonObject);
        if (!StringUtils.isEmpty(accessToken)) {
            JSONObject data = JSONObject.parseObject(accessToken);
            String newToken = data.getString("access_token");
            if (StringUtils.isNotBlank(newToken)) {
                redisUtil.set(SysConstant.access_token, newToken, SysConstant.base_redis_time);
                return newToken;
            }
        }
        logger.error("access_token获取失败，jsonObject={}", jsonObject);
        throw new RuntimeException("token获取失败!");
    }

}
